﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Text;
using System.Threading;

namespace XXF.BaseService.ServiceCenter.SystemRuntime
{
    /// <summary>
    /// 普通帮助类
    /// </summary>
    public class CommonHelper
    {
        /// <summary>
        /// 获取文件夹大小
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        public static long DirSize(DirectoryInfo d)
        {
            long Size = 0;
            // 所有文件大小.
            FileInfo[] fis = d.GetFiles();
            foreach (FileInfo fi in fis)
            {
                Size += fi.Length;
            }
            // 遍历出当前目录的所有文件夹.
            DirectoryInfo[] dis = d.GetDirectories();
            foreach (DirectoryInfo di in dis)
            {
                Size += DirSize(di);   //这就用到递归了，调用父方法,注意，这里并不是直接返回值，而是调用父返回来的
            }
            return (Size);
        }
        /// <summary>
        /// 获取当前文件夹大小
        /// </summary>
        /// <returns></returns>
        public static long CurrentDirSize()
        {
            var dir = new DirectoryInfo(System.AppDomain.CurrentDomain.BaseDirectory);
            if (dir.Exists)
            {
                return DirSize(dir);
            }
            return 0;
        }

        /// <summary>
        /// 获取当前服务器默认ip信息
        /// </summary>
        /// <returns></returns>
        public static string GetDefaultIP()
        {
            try
            {
                IPHostEntry ipHost = Dns.Resolve(Dns.GetHostName());

                foreach (var item in ipHost.AddressList)
                {
                    if (IsInnerIP(item.ToString()))
                    {
                        return item.ToString();
                    }
                }
            }
            catch (Exception exp)
            { }
            return "";
        }

        #region 内网地址判断
        /// <summary>
        /// 判断IP地址是否为内网IP地址
        /// </summary>
        /// <param name="ipAddress">IP地址字符串</param>
        /// <returns></returns>
        private static bool IsInnerIP(String ipAddress)
        {
            bool isInnerIp = false;
            long ipNum = GetIpNum(ipAddress);
            /**
               私有IP：A类  10.0.0.0-10.255.255.255
                       B类  172.16.0.0-172.31.255.255
                       C类  192.168.0.0-192.168.255.255
                       当然，还有127这个网段是环回地址   
              **/
            long aBegin = GetIpNum("10.0.0.0");
            long aEnd = GetIpNum("10.255.255.255");
            long bBegin = GetIpNum("172.16.0.0");
            long bEnd = GetIpNum("172.31.255.255");
            long cBegin = GetIpNum("192.168.0.0");
            long cEnd = GetIpNum("192.168.255.255");
            isInnerIp = IsInner(ipNum, aBegin, aEnd) || IsInner(ipNum, bBegin, bEnd) || IsInner(ipNum, cBegin, cEnd) || ipAddress.Equals("127.0.0.1");
            return isInnerIp;
        }

        /// <summary>
        /// 把IP地址转换为Long型数字
        /// </summary>
        /// <param name="ipAddress">IP地址字符串</param>
        /// <returns></returns>
        private static long GetIpNum(String ipAddress)
        {
            String[] ip = ipAddress.Split('.');
            long a = int.Parse(ip[0]);
            long b = int.Parse(ip[1]);
            long c = int.Parse(ip[2]);
            long d = int.Parse(ip[3]);

            long ipNum = a * 256 * 256 * 256 + b * 256 * 256 + c * 256 + d;
            return ipNum;
        }

        /// <summary>
        /// 判断用户IP地址转换为Long型后是否在内网IP地址所在范围
        /// </summary>
        /// <param name="userIp"></param>
        /// <param name="begin"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        private static bool IsInner(long userIp, long begin, long end)
        {
            return (userIp >= begin) && (userIp <= end);
        }
        #endregion

        private const string PortReleaseGuid = "8875BD8E-4D5B-11DE-B2F4-691756D89593";
        /// <summary>
        /// 获取当前服务器可用tcp端口
        /// </summary>
        /// <param name="startPort"></param>
        /// <param name="endPort"></param>
        /// <returns></returns>
        public static int FindNextAvailableTCPPort(int startPort, int endPort)
        {
            int port = startPort;
            bool isAvailable = true;

            var mutex = new Mutex(false,
                string.Concat("Global/", PortReleaseGuid));
            mutex.WaitOne();
            try
            {
                IPGlobalProperties ipGlobalProperties =
                    IPGlobalProperties.GetIPGlobalProperties();
                IPEndPoint[] endPoints =
                    ipGlobalProperties.GetActiveTcpListeners();

                do
                {
                    if (!isAvailable)
                    {
                        port++;
                        isAvailable = true;
                    }

                    foreach (IPEndPoint endPoint in endPoints)
                    {
                        if (endPoint.Port != port) continue;
                        isAvailable = false;
                        break;
                    }

                } while (!isAvailable && port < endPort);

                if (!isAvailable)
                    throw new ApplicationException("Not able to find a free TCP port.");

                return port;
            }
            finally
            {
                mutex.ReleaseMutex();
            }
        }

        /// <summary>
        /// 相同机器,同一个服务目录产生的sessionid不变
        /// </summary>
        /// <returns></returns>
        public static long CreateSessionID()
        {
            string mac = "";
            var macs = GetMacByNetworkInterface();
            if (macs.Count >= 0)
                mac = macs[0];
            string dir = System.AppDomain.CurrentDomain.BaseDirectory;
            long session = (mac + "_" + dir).GetHashCode();
            return session;
        }

        /// <summary>
        /// 相同机器,同一个客户端目录产生的sessionid不变
        /// </summary>
        /// <returns></returns>
        public static long CreateSessionIDOfClient(string servicenamespace)
        {
            string mac = "";
            var macs = GetMacByNetworkInterface();
            if (macs.Count >= 0)
                mac = macs[0];
            string dir = System.AppDomain.CurrentDomain.BaseDirectory;
            long session = (mac + "_" + dir + "_" + servicenamespace).GetHashCode();
            return session;
        }

        ///<summary>
        /// 通过NetworkInterface读取网卡Mac
        ///</summary>
        ///<returns></returns>
        private static List<string> GetMacByNetworkInterface()
        {
            List<string> macs = new List<string>();
            NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface ni in interfaces)
            {
                macs.Add(ni.GetPhysicalAddress().ToString());
            }
            return macs;
        }
        /// <summary>
        /// 获取当前程序集版本号
        /// </summary>
        /// <param name="assembly"></param>
        /// <returns></returns>
        public static double GetCustomVersion(Assembly assembly)
        {
            int major = assembly.GetName().Version.Major;
            int Minor = assembly.GetName().Version.Minor;
            return major + double.Parse("0." + Minor);
        }
        /// <summary>
        /// 下载Thrift.exe文件用于生成thrift协议
        /// </summary>
        /// <returns></returns>
        public static string DownloadThriftExe(string path)
        {
            try
            {
                using (WebClient wc = new WebClient())
                {
                    wc.DownloadFile(SystemConfigHelper.WebSite.TrimEnd('/') + "/download/" + System.IO.Path.GetFileName(path), path);
                }
            }
            catch (Exception exp)
            {
                throw new ServiceCenterException("下载thrift.exe文件失败", exp);
            }
            return "thrift-0.9.2.exe";
        }
    }
}
